package com.baizhi.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    private final MyUserDetailService myUserDetailService;

    public WebSecurityConfigurer(MyUserDetailService myUserDetailService) {
        this.myUserDetailService = myUserDetailService;
    }

    // @Bean
    // public UserDetailsService userDetailsService(){
    //     InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
    //     userDetailsService.createUser(User.withUsername("aaa").password("{noop}123").roles("admin").build());
    //     return userDetailsService;
    // }

    //修改 springboot 对 security 默认配置中，工厂中默认创建的AuthenticationManager
    // @Autowired
    // public void initialize(AuthenticationManagerBuilder builder) {
    //     System.out.println("springboot 默认配置：" + builder);
    // }

    //自定义AuthenticationManager 推荐，并没有在工厂中暴露出来
    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        System.out.println("自定义AuthenticationManager：" + builder);
        builder.userDetailsService(myUserDetailService);
    }

    //作⽤: ⽤来将⾃定义AuthenticationManager在⼯⼚中进⾏暴露,可以在任何位置注⼊
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/toLogin").permitAll() //放行的是/login.html请求，不是login.html页面
                .mvcMatchers("/index").permitAll() //放行资源必须写在任何前面
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/toLogin") //用来指定默认登录页面的请求路径，注意：一旦自定义登录页面以后必须指定登录url
                .loginProcessingUrl("/doLogin") //指定处理登录请求url
                .usernameParameter("uname")
                .passwordParameter("passwd")
                // .successForwardUrl("/index") //认证成功forward跳转路径，始终在认证成功之后跳转到指定请求
                // .defaultSuccessUrl("/hello") //认证成功之redirect后跳转，根据上一个保存的请求进行成功跳转
                .successHandler(new MyAuthenticationSuccessHandler()) //认证成功时处理，前后端分离解决方案
                // .failureForwardUrl("/login.html") //认证失败之后forward跳转
                // .failureUrl("/login.html") //默认，认证失败之后redirect跳转
                .failureHandler(new MyAuthenticationFailureHandler()) //用来自定义认证失败之后处理，前后端分离解决方案
                .and()
                .logout()
                // .logoutUrl("/logout") //指定注销登录url，默认请求方式必须：GET
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/aa", "GET"),
                        new AntPathRequestMatcher("/bb", "POST")
                ))
                .invalidateHttpSession(true) //默认会话失效
                .clearAuthentication(true) //默认清除认证标记
                // .logoutSuccessUrl("/toLogin") //注销登录 成功之后跳转页面
                .logoutSuccessHandler(new MyLogoutSuccessHandler()) //注销登录成功之后处理
                .and()
                .csrf().disable();//禁止csrf跨站请求保护

    }

}
